package org.nlp2rdf.navigator.refactored;

import com.hp.hpl.jena.query.ResultSetRewindable;
import org.apache.log4j.Logger;
import org.dllearner.kb.sparql.Cache;
import org.dllearner.kb.sparql.SPARQLTasks;
import org.dllearner.kb.sparql.SparqlEndpoint;
import org.nlp2rdf.navigator.client.exception.NKEQueryException;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;

public class SparqlService implements ISparqlService {
    private static final Logger logger = Logger.getLogger(SparqlService.class);

    private final String sparqlEndpointURL;
    private final String cacheDir;
    private final List<String> defaultGraphList;


    private final SPARQLTasks sparqlTask;

    public SparqlService(String sparqlEndpointURL) {
        this(sparqlEndpointURL, null, null);
    }

    public SparqlService(String sparqlEndpointURL, String cacheDir, List<String> defaultGraphList) {
        this.sparqlEndpointURL = sparqlEndpointURL;
        this.cacheDir = cacheDir;
        this.defaultGraphList = (defaultGraphList == null) ? new ArrayList<String>()
                : defaultGraphList;

        Cache c = null;
        SPARQLTasks st = null;
        try {
            if (this.cacheDir != null) {
                c = new Cache(cacheDir, true);
            }
            URL tmpURL = new URL(sparqlEndpointURL);
            SparqlEndpoint s = new SparqlEndpoint(tmpURL, defaultGraphList, new ArrayList<String>());

            st = (c == null) ? new SPARQLTasks(s) : new SPARQLTasks(c, s);
        } catch (MalformedURLException e) {
            String msg = sparqlEndpointURL + " is not a valid entry for sparqlEndpointURL";
            logger.error(msg, e);
        }
        sparqlTask = st;
    }


    public ResultSetRewindable queryAsResultSet(String sparqlQuery) throws NKEQueryException {
        ResultSetRewindable rsw = null;
        try {
            logger.trace("sending query");
            rsw = sparqlTask.queryAsResultSet(sparqlQuery);
            logger.trace("query successfull");
        } catch (Exception e) {
            String msg = "Sparql query failed \n" + sparqlQuery + "\n";
            logger.error(msg, e);
            throw new NKEQueryException(msg);
        }
        return rsw;
    }

    public SortedSet<String> queryAsSet(String sparqlQueryString, String variable) throws NKEQueryException {
        SortedSet<String> rsw = null;
        try {
            logger.trace("sending query");
            rsw = sparqlTask.queryAsSet(sparqlQueryString, variable);
            logger.trace("query successfull");
        } catch (Exception e) {
            String msg = "Sparql query failed \n" + sparqlQueryString + "\n" + e.getMessage();
            logger.error(msg);
            throw new NKEQueryException(msg);
        }
        return rsw;
    }

    public int queryAsCount(String sparqlQuery) throws NKEQueryException {
        int ret = -1;
        try {
            ret = sparqlTask.queryAsCount(sparqlQuery);
        } catch (Exception e) {
            String msg = "Sparql query failed \n" + e.getMessage();
            logger.error(msg);
            throw new NKEQueryException(msg);
        }
        return ret;

    }

    public String getSparqlEndpointURL() {
        return sparqlEndpointURL;
    }

    public String getCacheDir() {
        return cacheDir;
    }

    public List<String> getDefaultGraphList() {
        return defaultGraphList;
    }

    public SPARQLTasks getSparqlTask() {
        return sparqlTask;
    }


}
